package dcutils.cards.mtg;

/**
 * Represents a single card in Magic the Gathering.<br/>
 * @author dca
 */
public abstract class Card implements PrettyPrintable {
	private String cardName;
	private ManaCost manaCost;
	private Rarity rarity;
	private Expansion expansion;
	private String typeLine;
	private String cardText;
	private String flavorText;
	private boolean legendary = false;

	public Card(
		String cardName,
		Rarity rarity,
		Expansion expansion,
		String typeLine
	) {
		setCardName(cardName);
		setRarity(rarity);
		setExpansion(expansion);
		setTypeLine(typeLine);
	} // END constructor

	public Card(
		String cardName,
		ManaCost manaCost,
		Rarity rarity,
		Expansion expansion,
		String typeLine
	) {
		setCardName(cardName);
		setManaCost(manaCost);
		setRarity(rarity);
		setExpansion(expansion);
		setTypeLine(typeLine);
	} // END constructor

	public String getCardName() {
		return this.cardName;
	} // END getCardName

	public Card setCardName(String name) {
		this.cardName = name;
		return this;
	} // END setCardName

	public ManaCost getManaCost() {
		return this.manaCost;
	} // END getManaCost

	public Card setManaCost(ManaCost mana) {
		this.manaCost = mana;
		return this;
	} // END setManaCost

	public Rarity getRarity() {
		return this.rarity;
	} // END getRarity

	public Card setRarity(Rarity rarity) {
		this.rarity = rarity;
		return this;
	} // END setRarity

	public Expansion getExpansion() {
		return this.expansion;
	} // END getExpansion

	public Card setExpansion(Expansion expansion) {
		this.expansion = expansion;
		return this;
	} // END setExpansion

	public String getTypeLine() {
		final String prefix = "Legendary ";
		return (isLegendary() && !this.typeLine.startsWith(prefix) ? prefix : "") + this.typeLine;
	} // END getTypeLine

	public Card setTypeLine(String line) {
		this.typeLine = line;
		return this;
	} // END setTypeLine

	public String getCardText() {
		return this.cardText;
	} // END getCardText

	public Card setCardText(String text) {
		this.cardText = text;
		return this;
	} // END setCardText

	public boolean hasCardText() {
		final String text = getCardText();
		return null != text && !"".equals(text);
	} // END hasCardText

	public String getFlavorText() {
		return this.flavorText;
	} // END getFlavorText

	public Card setFlavorText(String text) {
		this.flavorText = text;
		return this;
	} // END setFlavorText

	public boolean hasFlavorText() {
		final String text = getFlavorText();
		return null != text && !"".equals(text);
	} // END hasFlavorText

	public Card setLegendary() {
		this.legendary = true;
		return this;
	} // END setLegendary

	public boolean isLegendary() {
		return this.legendary;
	} // END isLegendary

	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer(1024);
		buffer.append(this.getClass().getSimpleName()); buffer.append(" [");

		buffer.append(String.format("%s = %s", "cardName", getCardName()));
		buffer.append(", ");
		buffer.append(String.format("%s = %s", "manaCost", getManaCost()));
		buffer.append(", ");
		buffer.append(String.format("%s = %s", "rarity", getRarity()));
		buffer.append(", ");
		buffer.append(String.format("%s = %s", "expansion", getExpansion()));
		buffer.append(", ");
		buffer.append(String.format("%s = %s", "typeLine", getTypeLine()));
		if(hasCardText()) buffer.append(", ");
		if(hasCardText()) buffer.append(String.format("%s = %s", "cardText", getCardText()));
		if(hasFlavorText()) buffer.append(", ");
		if(hasFlavorText()) buffer.append(String.format("%s = %s", "flavorText", getFlavorText()));

		buffer.append("]");
		return buffer.toString();
	} // END toString

	@Override
	public boolean equals(Object obj) {
		if(null == obj) {
			return false;
		} else if(obj instanceof Card) {
			Card card = (Card)obj;
			return this.toString().equals(card.toString());
		} else {
			return false;
		} // END if/else
	} // END equals

	@Override
	public int hashCode() {
		int hashCode = 101;
		hashCode = (11 * hashCode) + (null == getCardName() ? -1   : getCardName().hashCode());
		hashCode = (11 * hashCode) + (null == getManaCost() ? -1   : getManaCost().hashCode());
		hashCode = (11 * hashCode) + (null == getRarity() ? -1     : getRarity().hashCode());
		hashCode = (11 * hashCode) + (null == getExpansion() ? -1  : getExpansion().hashCode());
		hashCode = (11 * hashCode) + (null == getTypeLine() ? -1   : getTypeLine().hashCode());
		hashCode = (11 * hashCode) + (null == getCardText() ? -1   : getCardText().hashCode());
		hashCode = (11 * hashCode) + (null == getFlavorText() ? -1 : getFlavorText().hashCode());
		return hashCode;
	} // END hashCode

	@Override
	public String prettyPrint() {
		StringBuffer buffer = new StringBuffer(1024);
		buffer.append(this.getClass().getSimpleName()); buffer.append(String.format(" [%n"));

		buffer.append(String.format("\t%s = %s", "cardName", getCardName()));
		buffer.append(String.format(",%n"));
		buffer.append(String.format("\t%s = %s", "manaCost", getManaCost().prettyPrint().replace("\t", "\t\t")));
		buffer.append(String.format(",%n"));
		buffer.append(String.format("\t%s = %s", "rarity", getRarity()));
		buffer.append(String.format(",%n"));
		buffer.append(String.format("\t%s = %s", "expansion", getExpansion()));
		buffer.append(String.format(",%n"));
		buffer.append(String.format("\t%s = %s", "typeLine", getTypeLine()));
		if(hasCardText()) buffer.append(String.format(",%n"));
		if(hasCardText()) buffer.append(String.format("\t%s = %s", "cardText", getCardText()));
		if(hasFlavorText()) buffer.append(String.format(",%n"));
		if(hasFlavorText()) buffer.append(String.format("\t%s = %s", "flavorText", getFlavorText()));

		buffer.append(String.format("%n]"));
		return buffer.toString();
	} // END prettyPrint

	public boolean isColorless() {
		if(null == manaCost) {
			return true;
		} else {
			for(Mana mana : manaCost) {
				if(mana instanceof ColorlessMana) continue;
				else return false;
			} // END loop
			return true;
		} // END if/else
	} // END isColorless
} // END class Card
